package uf.audit.controller;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.json.FastJson;
import com.jfinal.plugin.activerecord.Record;
import redis.clients.jedis.Jedis;
import uf.audit.db.*;
import uf.audit.db.support.ThreadPoolPlugin;
import uf.audit.excel.ReadExcel;
import uf.audit.quene.MessageQueue;
import uf.audit.util.Consts;
import uf.audit.util.Controller;
import uf.audit.util.Utils;

import javax.jms.*;
import javax.jms.Queue;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 主控制器类(一般权限)
 *
 * @author sunny
 */
@Controller(url = "/", view = "/WEB-INF/pages/")
public class IndexController extends PubController {
    //定义全局的redis
    public Jedis jedis = new Jedis("localhost");

    //定义全局的messageMQ
    static MessageQueue messageQueue = new MessageQueue();
    static ThreadPoolPlugin threadPoolPlugin = new ThreadPoolPlugin();

    static {
        ExecutorService es = Executors.newFixedThreadPool(threadPoolPlugin.getCoreThread());
        es.execute(new Runnable() {
            //@Override
            public void run() {
//                try {
//                    messageQueue.receiveTestSubjects();
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }
                try {
                    Connection conn = messageQueue.getConnection();
                    Session session = messageQueue.getSession(conn);
                    Queue queue = session.createQueue(MessageQueue.TEST_QUEUE);
                    MessageConsumer cusumer = session.createConsumer(queue);
                    while (true) {
                        try {
                            Message msg = cusumer.receive(10000);
                            if (msg != null) {
                                HashMap<String, Object> map = (HashMap<String, Object>) ((ObjectMessage) msg).getObject();
                                Object questions = map.get("questions");//题目列表
                                List<String> question_list = (List<String>) questions;
                                Object answer = map.get("answer");//答案列表
                                Map<String, String> answer_map = (Map<String, String>) answer;
                                //将所有试题放入数据库
                                for (int i = 0; i < question_list.size(); i++) {
                                    String jsonstr = question_list.get(0);
                                    JSONArray jsonArray = JSON.parseArray(jsonstr);
                                    for (int l = 0; l < jsonArray.size(); l++) {
                                        JSONObject json = jsonArray.getJSONObject(l);//获取jsonobject
                                        JSONObject jsonObject = json.getJSONObject("columns");//通过可以获取value
                                        jsonObject.remove("answer");
                                        Test.dao.update(jsonObject);
                                    }
                                }
                                //将所有的答案放入数据库
                                for (String key : answer_map.keySet()) {
                                    String answer_item = answer_map.get(key);
                                    JSONObject jsonObject = JSON.parseObject(answer_item);
                                    TestOpt.dao.update(jsonObject);
                                }
                                //将所有分数更新列表存入数据库
                                Object marking_update = map.get("marking-update");//更新分数列表
                                if (marking_update != null) {
                                    JSONObject jsonObject = (JSONObject) marking_update;
                                    Marking.dao.update(jsonObject);
                                }
                                //将所有分数插入到数据库
                                Object marking_insert = map.get("marking-insert");//插入分数列表
                                if (marking_insert != null) {
                                    Marking marking = (Marking) marking_insert;
                                    marking.save();
                                }
                            } else {
                            }
                        } catch (JMSException e) {
                            e.printStackTrace();
                        }
                    }
                } catch (Exception e) {
                }

            }
        });
        es.shutdown();
    }

    /*
     * 首页
     */
    public void index() {
        if (Utils.isLogin(this)) { // 如果已经登录
            render("index.html");
        } else { // 未登录
            redirect("/login");
        }
    }

    /*
     * 考试系统
     */
    public void testnav() {
        render("testnav.html");
    }

    // 我的考卷列表
    public void getmytests() {
        String userbh = Utils.getLogin(this);
        if ("audittest".equals(userbh)) {
            List<Record> list = new ArrayList<Record>();
            Record record = new Record();
            record.set("enabled", 0);
            record.set("modelname", "游客考试");
            record.set("modelbh", "audittest");
            list.add(record);
            renderJson(list);
        } else {
            renderJson(TestModel.dao.getownmodel(userbh, Consts.AUTH_TEST));
        }
    }

    private long processTime(String t, int minutes) {
        long diff = 0;
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date d1 = df.parse(t);
            diff = d1.getTime() + (minutes * 1000 * 60);
        } catch (Exception e) {
        }
        return diff;
    }

    // 当前用户是否是超级管理员
    private boolean isAdmin() {
        Boolean isadmin = (Boolean) getSessionAttr(Consts.AUTH_ADMIN_STR);
        return isadmin;
    }

    /*
     * 考试试卷
     */
    public void mytest() {
        String modelbh = getPara("modelbh");
        String full = getPara("full", null); // 是否采用全部显示模式
        String userbh = Utils.getLogin(this);
        if (userbh == null || modelbh == null) {

        } else if ("audittest".equals(userbh)) {
            setSessionAttr("testbh", "audittest");
            setSessionAttr("start", new Date());//考试开始时间
            if (null == jedis.hget("audittest", "minute") || "".equals(jedis.hget("audittest", "minute"))) {
                jedis.hset("audittest", "minute", "60");
            }
//            setSessionAttr("minute", 60);//考试时长
            Date time = getSessionAttr("start");
            String minutes = jedis.hget("audittest", "minute");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String starttime = sdf.format(time);
            long endTime = processTime(starttime, Integer.valueOf(minutes));
            setSessionAttr("endTime", endTime);
        } else {
            setSessionAttr("myBh", userbh);
            setSessionAttr("myModelBh", modelbh);
            // 是否存在本人的试卷模板
            boolean isadmin = isAdmin();
            if (!isadmin) { // 如果不是系统管理员，需要校验是否能访问试卷
                if (!Authentic.dao.checkTestAuthentic(modelbh, userbh)) {
                    renderError(401);
                    return;
                }
            } else {
                userbh = Consts.ADMIN_FIX;
            }
            TestModel model = TestModel.dao.getplan(modelbh);
            String modelname = model.getStr("modelname");
            setSessionAttr("modelname", modelname);
            Test t = Test.dao.getTestWithModelBh(userbh, modelbh);
            if (t == null) { // 还没有找到考试信息，创建它，完整复制一份出来
                // 获取 admin 的生产的试卷模板
                t = Test.dao.cloneTestFromModel(modelbh, userbh);
                User u = User.dao.getuser(userbh);
                String username = u.getStr("username");
                if ("audittest".equals(username)) {
                    Test tt = Test.dao.gettest(t.getStr("testbh"));
                    Test.dao.uaptest(t.getStr("testbh"));
                    tt.set("finished", false);
                    tt.set("starttime", new Date());
                    tt.update();
                }
                setSessionAttr("testbh", t.getStr("testbh"));
            } else {
                User u = User.dao.getuser(userbh);
                String username = u.getStr("username");
                setSessionAttr("testbh", t.getStr("testbh"));
            }
            if (!isadmin) {
                String starttime = t.getStr("starttime");
                Integer minutes = t.getInt("minutes");
                long endTime = processTime(starttime, minutes);
                setSessionAttr("endTime", endTime);
            }
        }
        if (full == null)
            render("test.html");
        else {
            render("test-full.html");
        }
    }

    public void setmytestfinished() {
        String testbh = (String) getSessionAttr("testbh");
        if (testbh == null) {
            renderError();
        } else {
            Test t = Test.dao.gettest(testbh);
            t.set("finished", true);
            t.update();
            renderSuccess();
        }
    }

    public void setmytestfinished1() {
        String status = getPara("status");
        String testbh = (String) getSessionAttr("testbh");
        String username = (String) getSessionAttr("username");
        String myBh = (String) getSessionAttr("myBh");
        String myModelBh = (String) getSessionAttr("myModelBh");
        String userbh = Utils.getLogin(this);
        int result;
        List<String> rsmap = new ArrayList<String>();
        int single_score;
        // int multi_score;
        HashMap<String, Object> map = new HashMap<String, Object>();
        map.put("username", userbh);
        map.put("questions", jedis.lrange("" + userbh + "^" + testbh, 0, 1000));
        map.put("answer", jedis.hgetAll(userbh + "^" + testbh + "^answer"));
        if (status == null) {
            Marking mark = new Marking();
            mark.getsinglecheckscoreBySession(myModelBh, userbh, testbh);
            if ("audittest".equals(userbh)) {
                rsmap = jedis.hmget("tourist^score", "score");
            } else {
                rsmap = mark.jedis.hmget(testbh + "singleScoreMap" + userbh, testbh + "singleScore" + userbh);
            }
            if (rsmap == null) {
                single_score = 0;
            } else {
                single_score = Integer.parseInt(rsmap.get(0));
            }
            result = single_score;
            Marking marking = mark.getmarking(myModelBh, myBh);
            if (marking == null) {
                marking = new Marking();
                marking.set("userbh", myBh);
                marking.set("modelbh", myModelBh);
                marking.set("score1", result);
                marking.set("markingbh", UUID.randomUUID().toString());
                map.put("marking-insert", marking);
            } else {
                marking.set("markingbh", marking.getStr("markingbh"));
                marking.set("score1", result);
                map.put("marking-update", marking);
            }
        } else {
            Marking mark = new Marking();
            single_score = 0;
            result = single_score;
            Marking marking = mark.getmarking(myModelBh, myBh);
            if (marking == null) {
                marking = new Marking();
                marking.set("userbh", myBh);
                marking.set("modelbh", myModelBh);
                marking.set("score1", result);
                marking.set("markingbh", UUID.randomUUID().toString());
                map.put("marking-insert", marking);
            } else {
                marking.set("markingbh", marking.getStr("markingbh"));
                marking.set("score1", result);
                map.put("marking-update", marking);
            }
        }
        try {
            if (!"audittest".equals(username)) {
                messageQueue.publishTestSubjects(map);//入队列
            }
        } catch (JMSException e) {
            e.printStackTrace();
        }
        if (testbh == null) {
            renderError();
        } else {
            if ("audittest".equals(username)) {
                getSession(true).setAttribute("score", result);
                jedis.del("tourist^score");//分数
                jedis.del("audittest");//时间
                jedis.del("tourist");//试题
                jedis.del(userbh + "^" + testbh + "change");
                jedis.del(userbh);
                jedis.del(userbh + "color");
            } else {
                Test t = Test.dao.gettest(testbh);
                t.set("finished", true);
                t.update();
                getSession(true).setAttribute("score", result);
            }
            renderJson(result);
        }

    }


    public void getmytestinfo() {
        String testbh = (String) getSessionAttr("testbh");
        String userbh = Utils.getLogin(this);
        if (testbh == null) {
            renderError();
        } else if ("audittest".equals(userbh)) {
            Test test = new Test();
            test.put("cnt", 10);
            test.put("modelname", "模拟考试");
            test.put("modelbh", "audittest");
            Date date = getSessionAttr("start");
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String start = simpleDateFormat.format(date);
            test.put("starttime", start);
            if (null != jedis.hget("audittest", "minute") || !"".equals(jedis.hget("audittest", "minute"))) {
                jedis.hset("audittest", "minute", "60");
                test.put("minutes", jedis.hget("audittest", "minute"));
            } else {
                test.put("minutes", jedis.hget("audittest", "minute"));
            }
            test.put("finished", false);
            test.put("enabled", 1);
            renderJson(test);
        } else {
            int cnt = TestQuestion.dao.getquestioncount(testbh);
            Test t = Test.dao.gettest(testbh);
            String modelname = (String) getSessionAttr("modelname");
            t.put("cnt", cnt);
            t.put("modelname", modelname);
            renderJson(t);
        }
    }

    public void getmytest() {
        int step = getParaToInt("step");
        String testbh = (String) getSessionAttr("testbh");
        String userbh = Utils.getLogin(this);
        if (testbh == null) {
            renderError();
        } else if ("audittest".equals(userbh)) {
            //获取redis中缓存的本地题目
            //从excel中获取题目
            List<Record> list = new ArrayList<Record>();//存放题目
            Map<String, String> map = jedis.hgetAll("tourist");
            String jsonstr = "";
            if (map.size() <= 0) {
                Map<String, String> result = new ReadExcel().readExcel("/java.xlsx");
                jedis.hmset("tourist", result);
                jsonstr = result.get("sort" + 1);
            } else {
                jsonstr = map.get("sort" + (step + 1));
            }
            JSONArray jsonArray = JSON.parseArray(jsonstr);
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject json = jsonArray.getJSONObject(i);//获取jsonobject
                JSONObject jsonObject = json.getJSONObject("columns");//通过可以获取value
                Record record = new Record().setColumns(FastJson.getJson().parse(jsonObject.toJSONString(), Map.class));
                record.set("sortno", (record.getInt("sortno") - 1));
                list.add(record);
            }
            renderJson(list);
        } else {
            renderJson(Test.dao.getquestionwithstep(testbh, step, userbh));
        }

    }

    public void postmytestitem() {
        String testbh = (String) getSessionAttr("testbh");
        String userbh = Utils.getLogin(this);
        boolean isadmin = isAdmin();
        if (!isadmin) {
            Long endTime = (Long) getSessionAttr("endTime");
            long nowTime = new Date().getTime();
            if (endTime.longValue() < nowTime) {
                String errMsg = "已经过期，不能再提交答案了";
                renderJson("{\"status\":\"outoftime\", \"msg\":\"" + errMsg + "\"}");
//				renderError("已经过期，不能再提交答案了");
                return;
            }
        }
        JSONArray arr = JSONArray.parseArray(getPostData());
        boolean result = true;
        if (!"audittest".equals(userbh)) {
            for (int i = 0, j = arr.size(); i < j; i++) {
                JSONObject obj = arr.getJSONObject(i);
                if ("1".equals(obj.getString("answer"))) {
                    jedis.sadd(userbh + "^" + testbh + "change", obj.getString("optbh"));
                }
                result = result && TestOpt.dao.updateRedis(obj, testbh, userbh, arr.size());
            }
        } else {
            for (int i = 0, j = arr.size(); i < j; i++) {
                JSONObject obj = arr.getJSONObject(i);
                if ("1".equals(obj.getString("answer"))) {
                    TestOpt.dao.updateTour(userbh, testbh, obj);
                }
            }
        }
        if (!"audittest".equals(userbh)) {
            //改变redis中已经拿到所有题的状态//答题状态
            result = result && TestOpt.dao.updateState(testbh, userbh);
        }
        if (result)
            renderSuccess();
        else
            renderError();
    }

    public void testscore() {
        render("testscore.html");
    }

    public void gettestscore() {
        String userbh = Utils.getLogin(this);
        List<TestModel> list = TestModel.dao.gettestscroes(userbh);
        renderJson(list);
    }

    public void scorecard() {
        String modelbh = getPara("modelbh");
        String userbh = getPara("userbh");
        Zjrd rd = Zjrd.dao.getzjrdwithbh(userbh, modelbh);
        if (rd == null) {
            //render("testscore.html");
            renderError();
            return;
        }
        if (rd.getInt("pass") == 1) {
            render("pass.html");
        } else {
            render("unpass.html");
        }
    }

    public void getscorecard() {
        String userbh = getPara("userbh");
        String modelbh = getPara("modelbh");
        Zjrd rd = Zjrd.dao.getzjrdwithbh(userbh, modelbh);
        renderJson(rd);
    }


    public void fenshu() {
        String modelbh = getPara("modelbh");
        if (modelbh == null) {
            Integer score = (Integer) getSession(true).getAttribute("score");
            if (score == null) score = 0;
            setAttr("score", score);
        } else {
            String ubh = Utils.getLogin(this);
            Marking mk = Marking.dao.getmarking(modelbh, ubh);
            Integer score1 = mk.getInt("score1");
            score1 = score1 == null ? 0 : score1;
            Integer score2 = mk.getInt("score2");
            score2 = score2 == null ? 0 : score2;
            setAttr("score", score1 + score2);
        }
        renderVelocity("fenshu.html");
    }

    //获取已经选择答案的题目列表
    public void getColors() {
        String userbh = Utils.getLogin(this);
        Set<String> set = jedis.smembers(userbh + "color");
        List<Integer> list = new ArrayList<Integer>();
        for (String s : set) {
            Integer integer = Integer.valueOf(s);
            list.add(integer);
        }
        renderJson(list);
    }

    //保存已经选择答案的题目列表
    public void saveColors() {
        String userbh = Utils.getLogin(this);
        String sortno = String.valueOf(getParaToInt("no"));
        jedis.sadd(userbh + "color", sortno);
        renderSuccess();
    }

}
